<template>
  <view class="uni-stat__select">
    <span v-if="label" class="uni-label-text hide-on-phone">{{ label + "：" }}</span>
    <view class="uni-stat-box" :class="{ 'uni-stat__actived': current }">
      <view class="uni-select" :class="{ 'uni-select--disabled': disabled }">
        <view class="uni-select__input-box" @click="toggleSelector">
          <view v-if="current" class="uni-select__input-text">{{ current }}</view>
          <view v-else class="uni-select__input-text uni-select__input-placeholder">{{ typePlaceholder }}</view>
          <view v-if="current && clear && !disabled" @click.stop="clearVal">
            <uni-icons type="clear" color="#c0c4cc" size="24" />
          </view>
          <view v-else>
            <uni-icons :type="showSelector ? 'top' : 'bottom'" size="14" color="#999" />
          </view>
        </view>
        <view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
        <view class="uni-select__selector" v-if="showSelector">
          <view class="uni-popper__arrow"></view>
          <scroll-view scroll-y="true" class="uni-select__selector-scroll">
            <view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
              <text>{{ emptyTips }}</text>
            </view>
            <view v-else class="uni-select__selector-item" v-for="(item, index) in mixinDatacomResData" :key="index" @click="change(item)">
              <text :class="{ 'uni-select__selector__disabled': item.disable }">{{ formatItemName(item) }}</text>
            </view>
          </scroll-view>
        </view>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
/**
 * DataChecklist 数据选择器
 * @description 通过数据渲染的下拉框组件
 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
 * @property {String} value 默认值
 * @property {Array} localdata 本地数据 ，格式 [{text:'',value:''}]
 * @property {Boolean} clear 是否可以清空已选项
 * @property {Boolean} emptyText 没有数据时显示的文字 ，本地数据无效
 * @property {String} label 左侧标题
 * @property {String} placeholder 输入框的提示文字
 * @property {Boolean} disabled 是否禁用
 * @event {Function} change  选中发生变化触发
 */

export default {
  name: "uni-data-select",
  mixins: [uniCloud.mixinDatacom || {}],
  props: {
    localdata: {
      type: Array,
      default() {
        return [];
      },
    },
    value: {
      type: [String, Number],
      default: "",
    },
    modelValue: {
      type: [String, Number],
      default: "",
    },
    label: {
      type: String,
      default: "",
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
    emptyTips: {
      type: String,
      default: "无选项",
    },
    clear: {
      type: Boolean,
      default: true,
    },
    defItem: {
      type: Number,
      default: 0,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"
    format: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      showSelector: false,
      current: "",
      mixinDatacomResData: [],
      apps: [],
      channels: [],
      cacheKey: "uni-data-select-lastSelectedValue",
    };
  },
  created() {
    this.debounceGet = this.debounce(() => {
      this.query();
    }, 300);
    if (this.collection && !this.localdata.length) {
      this.debounceGet();
    }
  },
  computed: {
    typePlaceholder() {
      const text = {
        "opendb-stat-app-versions": "版本",
        "opendb-app-channels": "渠道",
        "opendb-app-list": "应用",
      };
      const common = this.placeholder;
      const placeholder = text[this.collection];
      return placeholder ? common + placeholder : common;
    },
    valueCom() {
      // #ifdef VUE3
      return this.modelValue;
      // #endif
      // #ifndef VUE3
      return this.value;
      // #endif
    },
  },
  watch: {
    localdata: {
      immediate: true,
      handler(val, old) {
        if (Array.isArray(val) && old !== val) {
          this.mixinDatacomResData = val;
        }
      },
    },
    valueCom(val, old) {
      this.initDefVal();
    },
    mixinDatacomResData: {
      immediate: true,
      handler(val) {
        if (val.length) {
          this.initDefVal();
        }
      },
    },
  },
  methods: {
    debounce(fn, time = 100) {
      let timer = null;
      return function (...args) {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          fn.apply(this, args);
        }, time);
      };
    },
    // 执行数据库查询
    query() {
      this.mixinDatacomEasyGet();
    },
    // 监听查询条件变更事件
    onMixinDatacomPropsChange() {
      if (this.collection) {
        this.debounceGet();
      }
    },
    initDefVal() {
      let defValue = "";
      if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) {
        defValue = this.valueCom;
      } else {
        let strogeValue;
        if (this.collection) {
          strogeValue = this.getCache();
        }
        if (strogeValue || strogeValue === 0) {
          defValue = strogeValue;
        } else {
          let defItem = "";
          if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
            defItem = this.mixinDatacomResData[this.defItem - 1].value;
          }
          defValue = defItem;
        }
        if (defValue || defValue === 0) {
          this.emit(defValue);
        }
      }
      const def = this.mixinDatacomResData.find((item) => item.value === defValue);
      this.current = def ? this.formatItemName(def) : "";
    },

    /**
     * @param {[String, Number]} value
     * 判断用户给的 value 是否同时为禁用状态
     */
    isDisabled(value) {
      let isDisabled = false;

      this.mixinDatacomResData.forEach((item) => {
        if (item.value === value) {
          isDisabled = item.disable;
        }
      });

      return isDisabled;
    },

    clearVal() {
      this.emit("");
      if (this.collection) {
        this.removeCache();
      }
    },
    change(item) {
      if (!item.disable) {
        this.showSelector = false;
        this.current = this.formatItemName(item);
        this.emit(item.value);
      }
    },
    emit(val) {
      this.$emit("input", val);
      this.$emit("update:modelValue", val);
      this.$emit("change", val);
      if (this.collection) {
        this.setCache(val);
      }
    },
    toggleSelector() {
      if (this.disabled) {
        return;
      }

      this.showSelector = !this.showSelector;
    },
    formatItemName(item) {
      let { text, value, channel_code } = item;
      channel_code = channel_code ? `(${channel_code})` : "";

      if (this.format) {
        // 格式化输出
        let str = "";
        str = this.format;
        for (let key in item) {
          str = str.replace(new RegExp(`{${key}}`, "g"), item[key]);
        }
        return str;
      } else {
        return this.collection.indexOf("app-list") > 0 ? `${text}(${value})` : text ? text : `未命名${channel_code}`;
      }
    },
    // 获取当前加载的数据
    getLoadData() {
      return this.mixinDatacomResData;
    },
    // 获取当前缓存key
    getCurrentCacheKey() {
      return this.collection;
    },
    // 获取缓存
    getCache(name = this.getCurrentCacheKey()) {
      let cacheData = uni.getStorageSync(this.cacheKey) || {};
      return cacheData[name];
    },
    // 设置缓存
    setCache(value, name = this.getCurrentCacheKey()) {
      let cacheData = uni.getStorageSync(this.cacheKey) || {};
      cacheData[name] = value;
      uni.setStorageSync(this.cacheKey, cacheData);
    },
    // 删除缓存
    removeCache(name = this.getCurrentCacheKey()) {
      let cacheData = uni.getStorageSync(this.cacheKey) || {};
      delete cacheData[name];
      uni.setStorageSync(this.cacheKey, cacheData);
    },
  },
};
</script>

<style lang="scss">
$uni-base-color: #6a6a6a !default;
$uni-main-color: #333 !default;
$uni-secondary-color: #909399 !default;
$uni-border-3: #e5e5e5;

/* #ifndef APP-NVUE */
@media screen and (max-width: 500px) {
  .hide-on-phone {
    display: none;
  }
}

/* #endif */
.uni-stat__select {
  display: flex;
  align-items: center;
  // padding: 15px;
  /* #ifdef H5 */
  cursor: pointer;
  /* #endif */
  width: 100%;
  flex: 1;
  box-sizing: border-box;
}

.uni-stat-box {
  width: 100%;
  flex: 1;
}

.uni-stat__actived {
  width: 100%;
  flex: 1;
  // outline: 1px solid #2979ff;
}

.uni-label-text {
  font-size: 14px;
  font-weight: bold;
  color: $uni-base-color;
  margin: auto 0;
  margin-right: 5px;
}

.uni-select {
  font-size: 14px;
  border: 1px solid $uni-border-3;
  box-sizing: border-box;
  border-radius: 4px;
  padding: 0 5px;
  padding-left: 10px;
  position: relative;
  /* #ifndef APP-NVUE */
  display: flex;
  user-select: none;
  /* #endif */
  flex-direction: row;
  align-items: center;
  border-bottom: solid 1px $uni-border-3;
  width: 100%;
  flex: 1;
  height: 35px;

  &--disabled {
    background-color: #f5f7fa;
    cursor: not-allowed;
  }
}

.uni-select__label {
  font-size: 16px;
  // line-height: 22px;
  height: 35px;
  padding-right: 10px;
  color: $uni-secondary-color;
}

.uni-select__input-box {
  height: 35px;
  position: relative;
  /* #ifndef APP-NVUE */
  display: flex;
  /* #endif */
  flex: 1;
  flex-direction: row;
  align-items: center;
}

.uni-select__input {
  flex: 1;
  font-size: 14px;
  height: 22px;
  line-height: 22px;
}

.uni-select__input-plac {
  font-size: 14px;
  color: $uni-secondary-color;
}

.uni-select__selector {
  /* #ifndef APP-NVUE */
  box-sizing: border-box;
  /* #endif */
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  width: 100%;
  background-color: #ffffff;
  border: 1px solid #ebeef5;
  border-radius: 6px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 3;
  padding: 4px 0;
}

.uni-select__selector-scroll {
  /* #ifndef APP-NVUE */
  max-height: 200px;
  box-sizing: border-box;
  /* #endif */
}

/* #ifdef H5 */
@media (min-width: 768px) {
  .uni-select__selector-scroll {
    max-height: 600px;
  }
}
/* #endif */

.uni-select__selector-empty,
.uni-select__selector-item {
  /* #ifndef APP-NVUE */
  display: flex;
  cursor: pointer;
  /* #endif */
  line-height: 35px;
  font-size: 14px;
  text-align: center;
  /* border-bottom: solid 1px $uni-border-3; */
  padding: 0px 10px;
}

.uni-select__selector-item:hover {
  background-color: #f9f9f9;
}

.uni-select__selector-empty:last-child,
.uni-select__selector-item:last-child {
  /* #ifndef APP-NVUE */
  border-bottom: none;
  /* #endif */
}

.uni-select__selector__disabled {
  opacity: 0.4;
  cursor: default;
}

/* picker 弹出层通用的指示小三角 */
.uni-popper__arrow,
.uni-popper__arrow::after {
  position: absolute;
  display: block;
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 6px;
}

.uni-popper__arrow {
  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
  top: -6px;
  left: 10%;
  margin-right: 3px;
  border-top-width: 0;
  border-bottom-color: #ebeef5;
}

.uni-popper__arrow::after {
  content: " ";
  top: 1px;
  margin-left: -6px;
  border-top-width: 0;
  border-bottom-color: #fff;
}

.uni-select__input-text {
  // width: 280px;
  width: 100%;
  color: $uni-main-color;
  white-space: nowrap;
  text-overflow: ellipsis;
  -o-text-overflow: ellipsis;
  overflow: hidden;
}

.uni-select__input-placeholder {
  color: $uni-base-color;
  font-size: 12px;
}

.uni-select--mask {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  z-index: 2;
}
</style>
